@@ -170,6 +170,7 @@ def upload_temperature(request):  | 
            ||
| 170 | 170 | 
                try:  | 
            
| 171 | 171 | 
                eqpt = ThermometerEquipmentInfo.objects.get(macid=macid, status=True)  | 
            
| 172 | 172 | 
                except ThermometerEquipmentInfo.DoesNotExist:  | 
            
| 173 | 
                + ThermometerMeasureLogInfo.objects.create(point_id=eqpt.point_id, macid=macid, name=name, sex=sex, birth_stamp=birth_stamp, phone=phone, start_stamp=start_stamp, end_stamp=end_stamp, temperature=temperature, upload_temperature_info=request.POST, status=False)  | 
            |
| 173 | 174 | 
                return response(ThermometerEquipmentStatusCode.THERMOMETER_EQUIPMENT_NOT_FOUND)  | 
            
| 174 | 175 | 
                 | 
            
| 175 | 176 | 
                try:  | 
            
                @@ -196,3 +197,65 @@ def upload_temperature(request):  | 
            ||
| 196 | 197 | 
                })  | 
            
| 197 | 198 | 
                 | 
            
| 198 | 199 | 
                return response()  | 
            
| 200 | 
                +  | 
            |
| 201 | 
                +  | 
            |
| 202 | 
                +def mqtt_upload_temperature(payload):  | 
            |
| 203 | 
                +    # Received `{"mac":"A4DA324E7A63","pkt":"215","chg_sta":true,"bat":"100","raw_temp":"4697,4696,4697","sta":"0","alg_temp":"4697,4696,4697","alg_gstr":0,"ble_rssi":-21,"wifi_rssi":-68,"current_time":"2021-08-08 15:22:59"}` from `esp/240AC4D3C1AC` topic
               | 
            |
| 204 | 
                + #  | 
            |
| 205 | 
                +    # {
               | 
            |
| 206 | 
                + # "mac": "A4DA324E7A63", # 体温贴 mac,固定 6 个字节,12 个字符  | 
            |
| 207 | 
                + # "pkt": "215", # 广播包包序为 85,有效包序范围[1, 255]  | 
            |
| 208 | 
                + # "chg_sta": true, # 充电状态,true 充电,false 未充电  | 
            |
| 209 | 
                + # "bat": "100", # 电量剩余 65%,有效电量范围[0, 100]  | 
            |
| 210 | 
                + # "raw_temp": "4697,4696,4697", # 三个原始温度数  | 
            |
| 211 | 
                + # "sta": "0", # 算法返回状态  | 
            |
| 212 | 
                + # "alg_temp": "4697,4696,4697", # 算法返回三个温度  | 
            |
| 213 | 
                + # "alg_gstr": 0, # 算法手臂姿态  | 
            |
| 214 | 
                + # "ble_rssi": -21, # 体温贴相对于底座的信号强度  | 
            |
| 215 | 
                + # "wifi_rssi": -68, # 底座网络信号强度  | 
            |
| 216 | 
                + # "current_time": "2021-08-08 15:22:59" # 底座接收到体温贴信息的实时时间  | 
            |
| 217 | 
                + # }  | 
            |
| 218 | 
                + try:  | 
            |
| 219 | 
                + payload = json.loads(payload)  | 
            |
| 220 | 
                + except Exception:  | 
            |
| 221 | 
                + return  | 
            |
| 222 | 
                +  | 
            |
| 223 | 
                +    macid = payload.get('mac', '')
               | 
            |
| 224 | 
                +    macid = f'{macid[:2]}:{macid[2:4]}:{macid[4:6]}:{macid[6:8]}:{macid[8:10]}:{macid[10:12]}'
               | 
            |
| 225 | 
                +    current_time = payload.get('current_time', '')
               | 
            |
| 226 | 
                + start_stamp = end_stamp = tc.string_to_timestamp(current_time)  | 
            |
| 227 | 
                +    # raw_temp = payload.get('raw_temp', '')
               | 
            |
| 228 | 
                +    alg_temp = payload.get('alg_temp', '')
               | 
            |
| 229 | 
                +  | 
            |
| 230 | 
                +    # temp = raw_temp.split(',') + alg_temp.split(',')
               | 
            |
| 231 | 
                +    temp = alg_temp.split(',')
               | 
            |
| 232 | 
                + temp = [int(t) for t in temp if t]  | 
            |
| 233 | 
                +  | 
            |
| 234 | 
                + if not temp:  | 
            |
| 235 | 
                + return  | 
            |
| 236 | 
                +  | 
            |
| 237 | 
                + temperature = max(temp) / 100  | 
            |
| 238 | 
                +  | 
            |
| 239 | 
                + try:  | 
            |
| 240 | 
                + eqpt = ThermometerEquipmentInfo.objects.get(macid=macid, status=True)  | 
            |
| 241 | 
                + except ThermometerEquipmentInfo.DoesNotExist:  | 
            |
| 242 | 
                + ThermometerMeasureLogInfo.objects.create(macid=macid, start_stamp=start_stamp, end_stamp=end_stamp, temperature=temperature, temperature_src=ThermometerMeasureLogInfo.MQTT, upload_temperature_info=payload, status=False)  | 
            |
| 243 | 
                + return  | 
            |
| 244 | 
                +  | 
            |
| 245 | 
                + try:  | 
            |
| 246 | 
                + point = IsolationPointInfo.objects.get(point_id=eqpt.point_id, status=True)  | 
            |
| 247 | 
                + except IsolationPointInfo.DoesNotExist:  | 
            |
| 248 | 
                + return  | 
            |
| 249 | 
                +  | 
            |
| 250 | 
                + point_measure_ymd = tc.local_string(format='%Y-%m-%d')  | 
            |
| 251 | 
                + point_measure_window = point.current_measure_window  | 
            |
| 252 | 
                +  | 
            |
| 253 | 
                + eqpt.last_submit_at = tc.utc_datetime()  | 
            |
| 254 | 
                + eqpt.save()  | 
            |
| 255 | 
                +  | 
            |
| 256 | 
                + ThermometerMeasureLogInfo.objects.create(point_id=eqpt.point_id, macid=macid, start_stamp=start_stamp, end_stamp=end_stamp, temperature=temperature, temperature_src=ThermometerMeasureLogInfo.MQTT, upload_temperature_info=payload)  | 
            |
| 257 | 
                +  | 
            |
| 258 | 
                + if point_measure_window:  | 
            |
| 259 | 
                +        ThermometerMeasureInfo.objects.update_or_create(point_id=eqpt.point_id, point_measure_ymd=point_measure_ymd, point_measure_window=point_measure_window, macid=macid, defaults={
               | 
            |
| 260 | 
                + 'temperature': temperature,  | 
            |
| 261 | 
                + })  | 
            
                @@ -0,0 +1,106 @@  | 
            ||
| 1 | 
                +# -*- coding: utf-8 -*-  | 
            |
| 2 | 
                +  | 
            |
| 3 | 
                +import logging  | 
            |
| 4 | 
                +import random  | 
            |
| 5 | 
                +import time  | 
            |
| 6 | 
                +  | 
            |
| 7 | 
                +from django_six import CompatibilityBaseCommand  | 
            |
| 8 | 
                +from paho.mqtt import client as mqtt_client  | 
            |
| 9 | 
                +from api.eqpt_views import mqtt_upload_temperature  | 
            |
| 10 | 
                +  | 
            |
| 11 | 
                +  | 
            |
| 12 | 
                +logger = logging.getLogger('console')
               | 
            |
| 13 | 
                +  | 
            |
| 14 | 
                +  | 
            |
| 15 | 
                +# defined(PRORON_MQTT_DOMESTIC_SERVER)  | 
            |
| 16 | 
                +# define MQTT_SERVER_TYPE MQTT_SERVER_TYPE_DOMAIN_NAME  | 
            |
| 17 | 
                +# define MQTT_BROKER_URI "china.mqtt.protontek.com" /* Domestic server "47.100.92.19" */  | 
            |
| 18 | 
                +# define MQTT_USERNAME "proton"  | 
            |
| 19 | 
                +# define MQTT_PASSWORD "proton123"  | 
            |
| 20 | 
                +# define MQTT_PORT 1883  | 
            |
| 21 | 
                +broker = 'china.mqtt.protontek.com'  | 
            |
| 22 | 
                +username = 'proton'  | 
            |
| 23 | 
                +password = 'proton123'  | 
            |
| 24 | 
                +port = 1883  | 
            |
| 25 | 
                +topic = 'esp/#'  | 
            |
| 26 | 
                +client_id = f'python-mqtt-{random.randint(0, 1000)}'
               | 
            |
| 27 | 
                +  | 
            |
| 28 | 
                +  | 
            |
| 29 | 
                +# MQTT连接  | 
            |
| 30 | 
                +def connect_mqtt():  | 
            |
| 31 | 
                + def on_connect(client, userdata, flags, rc):  | 
            |
| 32 | 
                + if rc == 0:  | 
            |
| 33 | 
                +            print('Connected to MQTT Broker')
               | 
            |
| 34 | 
                + else:  | 
            |
| 35 | 
                +            print('Failed to connect, return code %d\n', rc)
               | 
            |
| 36 | 
                + # Set Connecting Client ID  | 
            |
| 37 | 
                +    print(f'Connected to MQTT Broker by client_id `{client_id}`')
               | 
            |
| 38 | 
                + client = mqtt_client.Client(client_id)  | 
            |
| 39 | 
                + client.username_pw_set(username, password=password)  | 
            |
| 40 | 
                + client.on_connect = on_connect  | 
            |
| 41 | 
                + client.connect(broker, port)  | 
            |
| 42 | 
                + return client  | 
            |
| 43 | 
                +  | 
            |
| 44 | 
                +  | 
            |
| 45 | 
                +# MQTT发布消息  | 
            |
| 46 | 
                +# from commands.management.commands.mqtt import publish_run  | 
            |
| 47 | 
                +# publish_run()  | 
            |
| 48 | 
                +def publish(client):  | 
            |
| 49 | 
                + msg_count = 0  | 
            |
| 50 | 
                + while True:  | 
            |
| 51 | 
                + time.sleep(1)  | 
            |
| 52 | 
                +        msg = f'messages: `{msg_count}`'
               | 
            |
| 53 | 
                + result = client.publish(topic, msg)  | 
            |
| 54 | 
                + # result: [0, 1]  | 
            |
| 55 | 
                + status = result[0]  | 
            |
| 56 | 
                + if status == 0:  | 
            |
| 57 | 
                +            print(f'Send `{msg}` to topic `{topic}`')
               | 
            |
| 58 | 
                + else:  | 
            |
| 59 | 
                +            print(f'Failed to send message to topic {topic}')
               | 
            |
| 60 | 
                + msg_count += 1  | 
            |
| 61 | 
                +  | 
            |
| 62 | 
                +  | 
            |
| 63 | 
                +def publish_run():  | 
            |
| 64 | 
                + client = connect_mqtt()  | 
            |
| 65 | 
                + client.loop_start()  | 
            |
| 66 | 
                + publish(client)  | 
            |
| 67 | 
                +  | 
            |
| 68 | 
                +  | 
            |
| 69 | 
                +# MQTT订阅消息  | 
            |
| 70 | 
                +def subscribe(client: mqtt_client):  | 
            |
| 71 | 
                + def on_message(client, userdata, msg):  | 
            |
| 72 | 
                +        # Received `{"mac":"A4DA324E7A63","pkt":"215","chg_sta":true,"bat":"100","raw_temp":"4697,4696,4697","sta":"0","alg_temp":"4697,4696,4697","alg_gstr":0,"ble_rssi":-21,"wifi_rssi":-68,"current_time":"2021-08-08 15:22:59"}` from `esp/240AC4D3C1AC` topic
               | 
            |
| 73 | 
                + #  | 
            |
| 74 | 
                +        # {
               | 
            |
| 75 | 
                + # "mac": "A4DA324E7A63", # 体温贴 mac,固定 6 个字节,12 个字符  | 
            |
| 76 | 
                + # "pkt": "215", # 广播包包序为 85,有效包序范围[1, 255]  | 
            |
| 77 | 
                + # "chg_sta": true, # 充电状态,true 充电,false 未充电  | 
            |
| 78 | 
                + # "bat": "100", # 电量剩余 65%,有效电量范围[0, 100]  | 
            |
| 79 | 
                + # "raw_temp": "4697,4696,4697", # 三个原始温度数  | 
            |
| 80 | 
                + # "sta": "0", # 算法返回状态  | 
            |
| 81 | 
                + # "alg_temp": "4697,4696,4697", # 算法返回三个温度  | 
            |
| 82 | 
                + # "alg_gstr": 0, # 算法手臂姿态  | 
            |
| 83 | 
                + # "ble_rssi": -21, # 体温贴相对于底座的信号强度  | 
            |
| 84 | 
                + # "wifi_rssi": -68, # 底座网络信号强度  | 
            |
| 85 | 
                + # "current_time": "2021-08-08 15:22:59" # 底座接收到体温贴信息的实时时间  | 
            |
| 86 | 
                + # }  | 
            |
| 87 | 
                + payload = msg.payload.decode()  | 
            |
| 88 | 
                +        print(f'Received `{payload}` from `{msg.topic}` topic')
               | 
            |
| 89 | 
                + mqtt_upload_temperature(payload)  | 
            |
| 90 | 
                +  | 
            |
| 91 | 
                + client.subscribe(topic)  | 
            |
| 92 | 
                + client.on_message = on_message  | 
            |
| 93 | 
                +  | 
            |
| 94 | 
                +  | 
            |
| 95 | 
                +def subscribe_run():  | 
            |
| 96 | 
                + client = connect_mqtt()  | 
            |
| 97 | 
                + subscribe(client)  | 
            |
| 98 | 
                + client.loop_forever()  | 
            |
| 99 | 
                +  | 
            |
| 100 | 
                +  | 
            |
| 101 | 
                +class Command(CompatibilityBaseCommand):  | 
            |
| 102 | 
                + def handle(self, *args, **options):  | 
            |
| 103 | 
                +  | 
            |
| 104 | 
                +        logger.info('MQTT client is dealing')
               | 
            |
| 105 | 
                +  | 
            |
| 106 | 
                + subscribe_run()  | 
            
                @@ -22,8 +22,8 @@ class ThermometerMeasureInfoAdmin(ReadOnlyModelAdmin, admin.ModelAdmin):  | 
            ||
| 22 | 22 | 
                 | 
            
| 23 | 23 | 
                 | 
            
| 24 | 24 | 
                class ThermometerMeasureLogInfoAdmin(ReadOnlyModelAdmin, admin.ModelAdmin):  | 
            
| 25 | 
                -    list_display = ('point_id', 'macid', 'sn', 'name', 'sex', 'birth_stamp', 'phone', 'start_stamp', 'end_stamp', 'temperature', 'status', 'updated_at', 'created_at')
               | 
            |
| 26 | 
                -    list_filter = ('point_id', 'status')
               | 
            |
| 25 | 
                +    list_display = ('point_id', 'macid', 'sn', 'name', 'sex', 'birth_stamp', 'phone', 'start_stamp', 'end_stamp', 'temperature', 'temperature_src', 'status', 'updated_at', 'created_at')
               | 
            |
| 26 | 
                +    list_filter = ('point_id', 'temperature_src', 'status')
               | 
            |
| 27 | 27 | 
                 | 
            
| 28 | 28 | 
                 | 
            
| 29 | 29 | 
                admin.site.register(IsolationPointInfo, IsolationPointInfoAdmin)  | 
            
                @@ -0,0 +1,18 @@  | 
            ||
| 1 | 
                +# Generated by Django 3.2.6 on 2021-08-08 11:03  | 
            |
| 2 | 
                +  | 
            |
| 3 | 
                +from django.db import migrations, models  | 
            |
| 4 | 
                +  | 
            |
| 5 | 
                +  | 
            |
| 6 | 
                +class Migration(migrations.Migration):  | 
            |
| 7 | 
                +  | 
            |
| 8 | 
                + dependencies = [  | 
            |
| 9 | 
                +        ('equipment', '0004_auto_20210712_0035'),
               | 
            |
| 10 | 
                + ]  | 
            |
| 11 | 
                +  | 
            |
| 12 | 
                + operations = [  | 
            |
| 13 | 
                + migrations.AddField(  | 
            |
| 14 | 
                + model_name='thermometermeasureloginfo',  | 
            |
| 15 | 
                + name='temperature_src',  | 
            |
| 16 | 
                + field=models.IntegerField(choices=[(1, '接口回调'), (2, 'MQTT')], default=1, help_text='用户体温来源', verbose_name='temperature_src'),  | 
            |
| 17 | 
                + ),  | 
            |
| 18 | 
                + ]  | 
            
                @@ -148,6 +148,14 @@ class ThermometerMeasureInfo(BaseModelMixin):  | 
            ||
| 148 | 148 | 
                 | 
            
| 149 | 149 | 
                 | 
            
| 150 | 150 | 
                class ThermometerMeasureLogInfo(BaseModelMixin):  | 
            
| 151 | 
                + CALLBACK = 1  | 
            |
| 152 | 
                + MQTT = 2  | 
            |
| 153 | 
                +  | 
            |
| 154 | 
                + TEMPERATURE_SRC_TUPLE = (  | 
            |
| 155 | 
                + (CALLBACK, '接口回调'),  | 
            |
| 156 | 
                + (MQTT, 'MQTT'),  | 
            |
| 157 | 
                + )  | 
            |
| 158 | 
                +  | 
            |
| 151 | 159 | 
                     point_id = models.CharField(_('point_id'), max_length=32, blank=True, null=True, help_text='隔离点唯一标识', db_index=True)
               | 
            
| 152 | 160 | 
                 | 
            
| 153 | 161 | 
                     macid = models.CharField(_('macid'), max_length=32, blank=True, null=True, help_text='设备号')
               | 
            
                @@ -163,6 +171,8 @@ class ThermometerMeasureLogInfo(BaseModelMixin):  | 
            ||
| 163 | 171 | 
                 | 
            
| 164 | 172 | 
                     temperature = models.FloatField(_('temperature'), default=0, help_text='用户体温')
               | 
            
| 165 | 173 | 
                 | 
            
| 174 | 
                +    temperature_src = models.IntegerField(_('temperature_src'), choices=TEMPERATURE_SRC_TUPLE, default=CALLBACK, help_text='用户体温来源')
               | 
            |
| 175 | 
                +  | 
            |
| 166 | 176 | 
                     upload_temperature_info = models.TextField(_('upload_temperature_info'), blank=True, null=True, help_text='测温结果上传信息')
               | 
            
| 167 | 177 | 
                 | 
            
| 168 | 178 | 
                class Meta:  | 
            
                @@ -2,6 +2,7 @@ StatusCode==1.0.0  | 
            ||
| 2 | 2 | 
                furl==2.1.2  | 
            
| 3 | 3 | 
                jsonfield==3.1.0  | 
            
| 4 | 4 | 
                mysqlclient==2.0.3  | 
            
| 5 | 
                +paho-mqtt==1.5.1  | 
            |
| 5 | 6 | 
                pysnippets==1.1.4  | 
            
| 6 | 7 | 
                requests==2.25.1  | 
            
| 7 | 8 | 
                rlog==0.3  | 
            
                @@ -1,3 +1,3 @@  | 
            ||
| 1 | 
                -ipdb==0.13.3  | 
            |
| 2 | 
                -ipython==7.18.1  | 
            |
| 1 | 
                +ipdb==0.13.9  | 
            |
| 2 | 
                +ipython==7.26.0  | 
            |
| 3 | 3 | 
                uwsgi==2.0.19.1  | 
            
                @@ -1,2 +1,2 @@  | 
            ||
| 1 | 
                -isort==5.4.2  | 
            |
| 2 | 
                -pycodestyle==2.6.0  | 
            |
| 1 | 
                +isort==5.9.3  | 
            |
| 2 | 
                +pycodestyle==2.7.0  | 
            
                @@ -305,7 +305,7 @@ DJANGO_SHORT_URL_REDIRECT_URL = ''  | 
            ||
| 305 | 305 | 
                 | 
            
| 306 | 306 | 
                # Django-We Settings  | 
            
| 307 | 307 | 
                DJANGO_WE_QUOTE_OR_NOT = True  | 
            
| 308 | 
                -DJANGO_WE_MODEL_DISPLAY_OR_NOT = True  | 
            |
| 308 | 
                +DJANGO_WE_MODEL_DISPLAY_OR_NOT = False  | 
            |
| 309 | 309 | 
                # Enable Cookie or not  | 
            
| 310 | 310 | 
                # DJANGO_WE_BASE_REDIRECT_SET_COOKIE = False  | 
            
| 311 | 311 | 
                # DJANGO_WE_USERINFO_REDIRECT_SET_COOKIE = True  |